#include "stdio.h"
#include "string.h"
#include "microTime.h"
#include "microCPU.h"
#include "microList.h"
#include "microMemory.h"
#include "microDelay.h"
#include "microTask.h"
#include "microMessage.h"


/* 创建消息控制块 */
int8_t cMrMessageCreate(MrMessageType **pptypeMessage, uint16_t usType, uint16_t usSize, uint32_t uiLengthTotal, uint32_t uiLengthInit)
{
    if((pptypeMessage == NULL) || (usSize < 1) || (uiLengthTotal < 1))
        return 1;

    /* 申请消息控制块 */
    if((*pptypeMessage = pvMrMemoryCalloc(1, sizeof(MrMessageType))) == NULL)
        return 2;

    /* 申请消息存储缓存 */
    if(((*pptypeMessage)->pIndexHead = pvMrMemoryMalloc(usSize * uiLengthTotal)) == NULL)
    {
        vMrMemoryFree(*pptypeMessage);
        return 3;
    }

    /* 初始化消息队列节点 */
    cMrListInit(&(*pptypeMessage)->listSend, 0);
    cMrListInit(&(*pptypeMessage)->listRead, 0);

    /* 初始化消息队列类型 */
    (*pptypeMessage)->type = usType;
    (*pptypeMessage)->size = usSize;

    /* 初始化消息队列参数 */
    (*pptypeMessage)->pIndexTail = (*pptypeMessage)->pIndexHead + usSize * uiLengthTotal;
    (*pptypeMessage)->pIndexNow  = (*pptypeMessage)->pIndexHead;
    (*pptypeMessage)->pIndexSend = (*pptypeMessage)->pIndexRead = (*pptypeMessage)->pIndexHead;

    /* 初始已有长度 */
    (*pptypeMessage)->pIndexNow += usSize * uiLengthInit;

    return 0;
}

/* 获取消息 */
int8_t cMessageRead(MrMessageType *ptypeMessage, void *pvValue, int64_t lTick)
{
    MrListType *ptypeListNow = NULL;
    MrTaskType *ptypeTaskNow = (MrTaskType *)g_ptypeMrTaskCurrent;
    int8_t cError = 2;

    if(ptypeMessage == NULL)
        return 1;

    /* 进入临界段 */
    vMrCpuDisableIsr();

    /* 消息队列中已没有消息 */
    if((ptypeMessage->pIndexNow <= ptypeMessage->pIndexHead) && (lTick != 0LL))
    {
        /* 从就绪、事件链表中移除 */
        cMrListRemove(&ptypeTaskNow->list);

        /* 插入到消息链表 */
        ptypeTaskNow->list.value = ptypeTaskNow->priority;
        cMrListInsert(&ptypeMessage->listRead, &ptypeTaskNow->list);

        /* 从延时链表中移除 */
        cMrListRemove(&ptypeTaskNow->listDelay);

        if(lTick > 0LL)
        {
            /* 计算延时 Tick 数量 */
            ptypeTaskNow->listDelay.value = lMrTickGet() + lTick;

            /* 插入到延时链表 */
            cMrListInsert(&g_typeMrListDelay, &ptypeTaskNow->listDelay);
        }
    }

    /* 退出临界段 */
    vMrCpuEnableIsr();

    /* 触发任务切换 */
    vMrCpuYield();

    /* 进入临界段 */
    vMrCpuDisableIsr();

    if(ptypeMessage->pIndexNow > ptypeMessage->pIndexHead)
    {
        ptypeMessage->pIndexNow -= ptypeMessage->size;

        /* 消息出队 - FIFO模式 */
        if(ptypeMessage->type == MR_MESSAGE_TYPE_FIFO)
        {
            if(pvValue != NULL)
                memcpy(pvValue, ptypeMessage->pIndexRead, ptypeMessage->size);

            ptypeMessage->pIndexRead += ptypeMessage->size;
            ptypeMessage->pIndexRead  = ptypeMessage->pIndexRead >= ptypeMessage->pIndexTail ? ptypeMessage->pIndexHead : ptypeMessage->pIndexRead;
        }
        /* 消息出队 - LIFO模式 */
        else
        {
            if(pvValue != NULL)
                memcpy(pvValue, ptypeMessage->pIndexNow, ptypeMessage->size);
        }

        /* 链表中有正在等待的任务 */
        if(ptypeMessage->listSend.pNext != &ptypeMessage->listSend)
        {
            ptypeListNow = ptypeMessage->listSend.pPrevious;
            ptypeTaskNow = (MrTaskType *)ptypeListNow->pElement;

            /* 从延时链表中移除 */
            cMrListRemove(&ptypeTaskNow->listDelay);

            /* 从消息链表中移除 */
            cMrListRemove(&ptypeTaskNow->list);

            /* 插入到就绪链表 */
            ptypeTaskNow->list.value = ptypeTaskNow->priority;
            cMrListInsert(&g_typeMrListTaskReady, &ptypeTaskNow->list);
        }

        cError = 0;
    }

    /* 退出临界段 */
    vMrCpuEnableIsr();

    /* 触发任务切换 */
    vMrCpuYield();

    return cError;
}

/* 发送消息 */
int8_t cMessageSend(MrMessageType *ptypeMessage, void *pvValue, int64_t lTick)
{
    MrListType *ptypeListNow = NULL;
    MrTaskType *ptypeTaskNow = NULL;
    int8_t cError = 2;

    if(ptypeMessage == NULL)
        return 1;

    /* 进入临界段 */
    vMrCpuDisableIsr();

    /* 消息队列中消息已满 */
    if((ptypeMessage->pIndexNow >= ptypeMessage->pIndexTail) && (lTick != 0LL))
    {
        /* 从就绪、事件链表中移除 */
        cMrListRemove(&ptypeTaskNow->list);

        /* 插入到消息链表 */
        ptypeTaskNow->list.value = ptypeTaskNow->priority;
        cMrListInsert(&ptypeMessage->listSend, &ptypeTaskNow->list);

        /* 从延时链表中移除 */
        cMrListRemove(&ptypeTaskNow->listDelay);

        if(lTick > 0LL)
        {
            /* 计算延时 Tick 数量 */
            ptypeTaskNow->listDelay.value = lMrTickGet() + lTick;

            /* 插入到延时链表 */
            cMrListInsert(&g_typeMrListDelay, &ptypeTaskNow->listDelay);
        }
    }

    /* 退出临界段 */
    vMrCpuEnableIsr();

    /* 触发任务切换 */
    vMrCpuYield();

    /* 进入临界段 */
    vMrCpuDisableIsr();

    if(ptypeMessage->pIndexNow < ptypeMessage->pIndexTail)
    {
        /* 消息入队 - FIFO模式 */
        if(ptypeMessage->type == MR_MESSAGE_TYPE_FIFO)
        {
            if(pvValue != NULL)
                memcpy(ptypeMessage->pIndexSend, pvValue, ptypeMessage->size);

            ptypeMessage->pIndexSend += ptypeMessage->size;
            ptypeMessage->pIndexSend  = ptypeMessage->pIndexSend >= ptypeMessage->pIndexTail ? ptypeMessage->pIndexHead : ptypeMessage->pIndexSend;
        }
        /* 消息入队 - LIFO模式 */
        else
        {
            if(pvValue != NULL)
                memcpy(ptypeMessage->pIndexNow, pvValue, ptypeMessage->size);
        }

        ptypeMessage->pIndexNow += ptypeMessage->size;

        /* 链表中有正在等待的任务 */
        if(ptypeMessage->listRead.pNext != &ptypeMessage->listRead)
        {
            ptypeListNow = ptypeMessage->listRead.pPrevious;
            ptypeTaskNow = (MrTaskType *)ptypeListNow->pElement;

            /* 从延时链表中移除 */
            cMrListRemove(&ptypeTaskNow->listDelay);

            /* 从消息链表中移除 */
            cMrListRemove(&ptypeTaskNow->list);

            /* 插入到就绪链表 */
            ptypeTaskNow->list.value = ptypeTaskNow->priority;
            cMrListInsert(&g_typeMrListTaskReady, &ptypeTaskNow->list);
        }

        cError = 0;
    }

    /* 退出临界段 */
    vMrCpuEnableIsr();

    /* 触发任务切换 */
    vMrCpuYield();

    return cError;
}
